package com.niiwoo.civet.account.service.local.refund.newRefund;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.niiwoo.civet.account.dao.entity.*;
import com.niiwoo.civet.account.dao.mapper.*;
import com.niiwoo.civet.account.dto.AccountAsyncChangeExtDTO;
import com.niiwoo.civet.account.dto.common.AsyncTransactionNotifyDTO;
import com.niiwoo.civet.account.dto.common.MoneyTotalDTO;
import com.niiwoo.civet.account.dto.request.SaveBillDetailRequest;
import com.niiwoo.civet.account.enums.*;
import com.niiwoo.civet.account.service.local.AccountBalanceLocalAsyncService;
import com.niiwoo.civet.account.service.local.AccountBalanceLocalService;
import com.niiwoo.civet.account.service.local.MoneyTotalLocalService;
import com.niiwoo.civet.account.service.local.bill.BillFacade;
import com.niiwoo.civet.account.service.local.bill.NiiwooBillFacade;
import com.niiwoo.civet.trade.dto.common.RefundCallBackForAccountDTO;
import com.niiwoo.civet.trade.service.refund.RepaymentDubboService;
import com.niiwoo.tripod.lanmao.enums.BusinessTypeEnum;
import com.niiwoo.tripod.lanmao.enums.TransactionTypeEnum;
import com.niiwoo.tripod.lanmao.properties.LanMaoProperties;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created by dell on 2018/1/31.
 */
@Slf4j
@Service
public class CallBackRefundLocalService {

    @Autowired
    private BatchTransOrderDetailMapperExt batchTransOrderDetailMapperExt;
    @Autowired
    private BatchTransOrderMapperExt batchTransOrderMapperExt;
    @Autowired
    private MoneyTotalLocalService moneyTotalLocalService;
    @Autowired
    private BatchTransOrderDetailBizMapperExt batchTransOrderDetailBizMapperExt;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private AccountAsyncChangeMapper accountAsyncChangeMapper;
    @Autowired
    private BillFacade billFacade;
    @Autowired
    private ProTransactionOrderMapperExt proTransactionOrderMapperExt;
    @Autowired
    private LanMaoProperties lanMaoProperties;
    @Autowired
    private AccountBalanceLocalAsyncService accountBalanceLocalAsyncService ;
    @Reference(version = "1.0.0")
    private RepaymentDubboService repaymentDubboService;
    @Autowired
    private RedissonClient redissonClient;

    private String refundCallBackLock = "refundCallBack:lock";

    /**
     * 回调处理入口
     *
     * @param list
     */
    public  void refundCallBack(List<AsyncTransactionNotifyDTO> list) {
        Assert.notEmpty(list, "批量交易还款结果不能为空");

        log.info("refundCallBack()-start-list.size()={}",list.size());

        List<String> batchNos = ((CallBackRefundLocalService)AopContext.currentProxy()).updateAllBatchTransOrderDetailStatus(list);
        if (batchNos.size()<1){
            log.info("isNeedHandle=false---return--");
            return;
        }
        log.info("----------回调处理批次号列表{}-",batchNos);
        for (String batchNo : batchNos){
            log.info("----------回调处理批次号{}-",batchNo);
            try{
                ((CallBackRefundLocalService) AopContext.currentProxy()).handSuccessRepayment(batchNo);
            }catch(Exception e){
                log.error("还款回调账户中心业务处理异常,batchNo={}",batchNo,e);
            }

        }

    }


    /**
     * 回调处理还款订单明细和订单
     *
     *
     * @param list
     * @return
     */
    @Transactional
    public List<String> updateAllBatchTransOrderDetailStatus(List<AsyncTransactionNotifyDTO> list) {
        //同步
        RLock lock = redissonClient.getLock(refundCallBackLock);
        try {
            lock.lock();
            Set<String> batchNoSuccess = new HashSet<>();

            //更新BatchTransOrderDetail状态
            Set<String> batchNos = new HashSet<>();

            int detailHandled = 0;
            for (AsyncTransactionNotifyDTO dto : list) {
                RefundStatusEnum status = RefundStatusEnum.valueOf(dto.getStatus());

                BatchTransOrderDetail detail = batchTransOrderDetailMapperExt.selectByDetailRequestNo(dto.getAsyncRequestNo());
                BatchTransOrderDetail detailUpdater = new BatchTransOrderDetail();
                detailUpdater.setStatus(status.getValue());
                detailUpdater.setId(detail.getId());
                int i = batchTransOrderDetailMapperExt.updateByPrimaryKeySelective(detailUpdater);
                if (i > 0) {
                    //受影响的批次
                    detailHandled++;
                    batchNos.add(detail.getBatchRequestNo());
                }
            }

            log.info("本次更新批次号{},更新明细条数{}", batchNos, detailHandled);
            if (batchNos.size() > 0) {
                for (String batchNo : batchNos) {

                    List<BatchTransOrderDetail> batchTransOrderDetails = batchTransOrderDetailMapperExt.selectByDetailByBatchNoNotSuccess(batchNo);
                    //没有全部处理成功
                    if (!CollectionUtils.isEmpty(batchTransOrderDetails)) {
                        log.info("batchTransOrderDetails.size()={}==", batchTransOrderDetails.size());
                        int handingNum = 0;
                        int failNum = 0;
                        for (BatchTransOrderDetail p : batchTransOrderDetails) {
                            if (p.getStatus() == RefundStatusEnum.HANDLING.getValue()) {
                                handingNum++;
                            } else if (p.getStatus() == RefundStatusEnum.FAIL.getValue()) {
                                failNum++;
                            }
                        }
                        if (handingNum + failNum == 0) {
                            batchNoSuccess.add(batchNo);
                        } else if (failNum > 0) {
                            log.error("有批次明细出现失败，batchNo={}", batchNo);
                        }
                    } else {//全部处理成功
                        log.info("===all success=batchNo{}==", batchNo);
                        batchNoSuccess.add(batchNo);
                    }
                }
            }
            log.info("batchNoSuccessSet=={}", batchNoSuccess);
            return new ArrayList(batchNoSuccess);
        } catch (Exception e) {
            log.error("还款回调处理异常", e);
        } finally {
            log.info("refund callBack unlock");
            lock.unlock();
        }
        return new ArrayList<>();
    }

    public  void refundCallBackForSuccess(String batchNoSuccess){
        //批次有明细数据
        int detailNum = batchTransOrderDetailMapperExt.countNumsByBatchNo(batchNoSuccess);
        if (detailNum > 0){
            int handingNum = batchTransOrderDetailMapperExt.countProjectNotSuccessByBatchNo(batchNoSuccess);
            if (handingNum == 0) {
                log.info("批次已经全部更新为成功,batchNo={}", batchNoSuccess);
                try {
                    ((CallBackRefundLocalService) AopContext.currentProxy()).handSuccessRepayment(batchNoSuccess);
                }catch (Exception e){
                    log.error("计划任务（被单）还款回调业务处理异常,batchNo={}",batchNoSuccess);
                }
            }
        }
    }

    /**
     * 按批次号处理
     * @param batchNo
     */
    @Transactional
    public void handSuccessRepayment(String batchNo){
        List<BatchTransOrderDetail> detailList = batchTransOrderDetailMapperExt.selectByDetailAllByBatchNo(batchNo);

        BatchTransOrder batchTransOrder = batchTransOrderMapperExt.selectOrderByBatchRequestNo(batchNo);
        Assert.notNull(batchTransOrder,"批次号记录不存在");
        BatchTransOrder batchTransOrderUpdate = new BatchTransOrder();
        batchTransOrderUpdate.setId(batchTransOrder.getId());
        batchTransOrderUpdate.setStatus(RefundStatusEnum.SUCCESS.getValue());
        int i = batchTransOrderMapperExt.updateByPrimaryKeyHandingSelective(batchTransOrderUpdate);
        if (i == 0){
            log.info("该批次号已处理过,batchNo={}",batchNo);
            return;
        }

        Set<RefundCallBackForAccountDTO> refundCallBackForAccountDTOSet = new HashSet();
        log.info("----------detailList-{}----",detailList.size());
        for (BatchTransOrderDetail p:detailList){
            log.info("-------BatchTransOrderDetail-{}--",p.getProjectId());
            RefundCallBackForAccountDTO dto = new RefundCallBackForAccountDTO();
            dto.setProjectId(p.getProjectId());
            dto.setBatchNo(p.getBatchRequestNo());
            dto.setBorrowerUserId(p.getBorrowUserId());
            refundCallBackForAccountDTOSet.add(dto);
        }
        //Map<Long, RefundCallBackForAccountDTO> mp = new HashMap<>();
        List<RefundCallBackForAccountDTO> resultList = new ArrayList<>();
        List<Long> resultListProjectIds = new ArrayList<>();
        refundCallBackForAccountDTOSet.forEach(setObj -> {
            if (setObj.getProjectId() != null) {
                //全部成功
                resultListProjectIds.add(setObj.getProjectId());
                log.info("-----------------------batchNo={}---",setObj.getBatchNo());
                RefundCallBackForAccountDTO dto = new RefundCallBackForAccountDTO();
                dto.setProjectId(setObj.getProjectId());
                dto.setBatchNo(setObj.getBatchNo());
                BatchTransOrder order = batchTransOrderMapperExt.selectOrderByBatchRequestNo(dto.getBatchNo());
                dto.setCurrentPeriod(order.getCurrentPeriod());
                dto.setBorrowerUserId(setObj.getBorrowerUserId());
                //mp.put(setObj.getProjectId(),dto);
                log.info("resultListProjectIds={}",resultListProjectIds);
                resultList.add(dto);
            }
        });
        log.info("----------resultList----{}",resultList.size());
        if (resultList.size() > 0) {
            log.info("标的号集合{},还款处理成功,通知交易中心", JSON.toJSONString(resultListProjectIds));

            List<BatchTransOrderDetail> refundResultDTOList = batchTransOrderDetailMapperExt.selectOrderDetailOneSuccessNewer(batchNo);
            log.info("--refundResultDTOList.size()-{}", refundResultDTOList.size());
            //余额更新
            List<MoneyTotalDTO> moneyTotalDTOS = this.updateAllAccountAmount(refundResultDTOList, batchTransOrder);
            log.info("--moneyTotalDTOS.size()---{}",moneyTotalDTOS.size());
            //统计金额更新
            moneyTotalLocalService.moneyTotal(moneyTotalDTOS);
            log.info("--moneyTotalLocalService.moneyTotal--end--resultListProjectIds={}",resultListProjectIds);
            //回调交易中心
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    super.afterCommit();
                    log.info("还款账户中心事物已提交，回调交易中心,batchNo={}",batchNo);
                    callBackToTradeCenterSuccess(resultList);
                }
            });
        } else {
            log.warn("本次通知无处理完毕的标的交易");
        }
    }

    /**
     * 回调交易中心
     *
     * @param list
     */
    public void callBackToTradeCenterSuccess(List<RefundCallBackForAccountDTO> list) {

        log.info("accountCenter->tradeCenter===callBackToTradeCenterSuccess()--{}",JSON.toJSONString(list));
        try {
            RpcContext.getContext().asyncCall(new Runnable() {
                @Override
                public void run() {
                    repaymentDubboService.repaymentCallBackForAccountNew(list);
                }
            });
        } catch (Exception e) {
            log.error("callBackToTradeCenterSuccess() invoke failed.", e);
        }
        log.info("accountCenter->tradeCenter===callBackToTradeCenterSuccess()--end--");

    }

    /**
     * 还款回调使用
     * 标的交易全部处理完成后，更新所有账单数据
     *
     * @param list
     * @param batchTransOrder
     * @return
     */
    public List<MoneyTotalDTO> updateAllAccountAmount(List<BatchTransOrderDetail> list, BatchTransOrder batchTransOrder) {
        List<MoneyTotalDTO> moneyTotalDTOList = new ArrayList<>();
        Map<String, JSONObject> refundFreezeMap = new HashMap<>();
        List<AccountAsyncChangeExtDTO> dtoList = new ArrayList<>();
        log.info("updateAllAccountAmount.RefundResultDTOList--{}", list.size());
        /*HintManager hintManager = HintManager.getInstance();
        hintManager.setMasterRouteOnly();*/
        ProTransactionOrder proTransactionOrders = proTransactionOrderMapperExt.queryProTransactionOrderByBatchRequestNo(batchTransOrder.getBatchRequestNo());

        for (BatchTransOrderDetail batchTransOrderDetail : list) {
            log.info("updateAllAccountAmount.dto--{}", JSON.toJSONString(batchTransOrderDetail));
            if (RefundStatusEnum.SUCCESS == RefundStatusEnum.enumOf(batchTransOrderDetail.getStatus())) {
                log.info("updateAllAccountAmount.dto--success");
                //BatchTransOrderDetail batchTransOrderDetail = batchTransOrderDetailMapperExt.selectByDetailRequestNo(dto.getAsyncRequestNo());
                Assert.notNull(batchTransOrderDetail, "没有相应的批量交易明细");
                List<BatchTransOrderDetailBiz> bizList = batchTransOrderDetailBizMapperExt.selectByDetailRequestNo(batchTransOrderDetail.getDetailRequestNo());
                Assert.notEmpty(bizList, "没有相应的批量交易业务明细");
                Integer currentPeriod = batchTransOrderDetail.getCurrentPeriod() == null? batchTransOrder.getCurrentPeriod() : batchTransOrderDetail.getCurrentPeriod();
                String borrowerUserId = batchTransOrder.getBorrowerUserId();
                log.info("bizList.size={},currentPeriod={},borrowerUserId={}", bizList.size(), currentPeriod, borrowerUserId);
                BigDecimal interestTotal = BigDecimal.ZERO;

                for (BatchTransOrderDetailBiz biz : bizList) {
                    log.info("DetailRequestNo={},amount={}", biz.getDetailRequestNo(), biz.getAmount());
                    AccountAsyncChangeExtDTO accountAsyncChangeRequestDTO = new AccountAsyncChangeExtDTO();
                    if (biz.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                        continue;
                    }
                    accountAsyncChangeRequestDTO.setId(snowflakeIdWorker.nextId());
                    accountAsyncChangeRequestDTO.setStatus((byte) 1);//初始状态
                    accountAsyncChangeRequestDTO.setAccountId(biz.getTargetAccountId());
                    //accountAsyncChangeRequestDTO.setAmount(biz.getAmount());
                    accountAsyncChangeRequestDTO.setProjectId(batchTransOrderDetail.getProjectId());
                    accountAsyncChangeRequestDTO.setRequestNo(biz.getDetailRequestNo());
                    accountAsyncChangeRequestDTO.setRelationUserId(borrowerUserId);
                    accountAsyncChangeRequestDTO.setOrderId(batchTransOrderDetail.getId());
                    accountAsyncChangeRequestDTO.setSecondSortCode("0");//默认值，无费用科目时,理论上不存在此场景
                    accountAsyncChangeRequestDTO.setInvestOrderId(biz.getInvestOrderId());

                    //如果是提前结清
                    if (biz.getExpectInterest().compareTo(BigDecimal.ZERO) > 0) {
                        //待收利息
                        MoneyTotalDTO interestToBeCollected = new MoneyTotalDTO();
                        interestToBeCollected.setAccountId(biz.getTargetAccountId());
                        interestToBeCollected.setAmount(biz.getExpectInterest().negate());
                        interestToBeCollected.setAmountType(AccountAmountTypeEnum.DUE_IN_INTEREST);
                        moneyTotalDTOList.add(interestToBeCollected);
                    }

                    //如果有利息,计算投资收益和待收利息
                    if (biz.getInterest().compareTo(BigDecimal.ZERO) > 0) {
                        log.info("biz.getInterest()={}", biz.getInterest());
                        //投资收益
                        MoneyTotalDTO incomeFromInvestment = new MoneyTotalDTO();
                        incomeFromInvestment.setAccountId(biz.getTargetAccountId());
                        incomeFromInvestment.setAmount(biz.getInterest());
                        incomeFromInvestment.setAmountType(AccountAmountTypeEnum.INVEST_INCOME);
                        moneyTotalDTOList.add(incomeFromInvestment);

                        interestTotal = interestTotal.add(biz.getInterest());

                        //待收利息
                        if (biz.getExpectInterest().compareTo(BigDecimal.ZERO) == 0) {
                            MoneyTotalDTO interestToBeCollected = new MoneyTotalDTO();
                            interestToBeCollected.setAccountId(biz.getTargetAccountId());
                            interestToBeCollected.setAmount(biz.getInterest().negate());
                            interestToBeCollected.setAmountType(AccountAmountTypeEnum.DUE_IN_INTEREST);
                            moneyTotalDTOList.add(interestToBeCollected);
                        }

                        AccountAsyncChangeExtDTO accountAsyncChangeRequestDTONew = new AccountAsyncChangeExtDTO();
                        accountAsyncChangeRequestDTO.setAmount(biz.getInterest());
                        BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChangeRequestDTONew);
                        List<SaveBillDetailRequest> saveBillDetailRequestList = new ArrayList<>();
                        SaveBillDetailRequest detailRequest = new SaveBillDetailRequest();
                        detailRequest.setBackTime(null);
                        detailRequest.setAmount(biz.getInterest());
                        if (biz.getBizType().equals(BusinessTypeEnum.COMPENSATORY.getValue())) {
                            //担保公司--》投资人
                            detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_INTEREST_GUARANTEE_COMPANY);
                            detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_INTEREST);

                        } else if (biz.getBizType().equals(BusinessTypeEnum.REPAYMENT.getValue())){
                            //借款人-》投资人
                            detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_INTEREST_BORROW);
                            detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_INTEREST);

                        }else {
                            //借款人-》担保公司
                            detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_INTEREST);
                        }

                        detailRequest.setCurrentPeriod(currentPeriod);
                        detailRequest.setRelationUserId(borrowerUserId);
                        detailRequest.setRelationAccountId(biz.getSourceAccountId());
                        saveBillDetailRequestList.add(detailRequest);

                        accountAsyncChangeRequestDTONew.setSecondSortCode(detailRequest.getBillSecondSubjectEnum().getCode());
                        accountAsyncChangeRequestDTONew.setSaveBillDetailRequestList(saveBillDetailRequestList);
                        dtoList.add(accountAsyncChangeRequestDTONew);
                    }

                    //如果有平台管理费,计算借款费用
                    if (biz.getManageFee().compareTo(BigDecimal.ZERO) > 0) {
                        log.info("biz.getManageFee()={}", biz.getManageFee());
                        MoneyTotalDTO manageFee = new MoneyTotalDTO();
                        manageFee.setAccountId(biz.getSourceAccountId());
                        manageFee.setAmount(biz.getManageFee());
                        manageFee.setAmountType(AccountAmountTypeEnum.BORROW_PLATFORM_MANAGER_FEE);
                        moneyTotalDTOList.add(manageFee);

                        AccountAsyncChangeExtDTO accountAsyncChangeRequestDTONew = new AccountAsyncChangeExtDTO();
                        accountAsyncChangeRequestDTO.setAmount(biz.getManageFee());
                        BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChangeRequestDTONew);
                        List<SaveBillDetailRequest> saveBillDetailRequestList = new ArrayList<>();
                        SaveBillDetailRequest detailRequest = new SaveBillDetailRequest();
                        detailRequest.setAmount(biz.getManageFee());
                        detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_MANAGE_SPEED_BORROWING);
                        detailRequest.setCurrentPeriod(currentPeriod);
                        detailRequest.setRelationUserId(borrowerUserId);
                        detailRequest.setRelationAccountId(biz.getSourceAccountId());
                        saveBillDetailRequestList.add(detailRequest);

                        accountAsyncChangeRequestDTONew.setSecondSortCode(detailRequest.getBillSecondSubjectEnum().getCode());
                        accountAsyncChangeRequestDTONew.setSaveBillDetailRequestList(saveBillDetailRequestList);
                        dtoList.add(accountAsyncChangeRequestDTONew);
                    }

                    //如果有本金,计算待收本金
                    if (biz.getCapital().compareTo(BigDecimal.ZERO) > 0) {
                        log.info("biz.getCapital()={}", biz.getCapital());
                        MoneyTotalDTO capital = new MoneyTotalDTO();
                        capital.setAccountId(biz.getTargetAccountId());
                        capital.setAmount(BigDecimal.ZERO.subtract(biz.getCapital()));
                        capital.setAmountType(AccountAmountTypeEnum.DUE_IN_CORPUS);
                        moneyTotalDTOList.add(capital);

                        AccountAsyncChangeExtDTO accountAsyncChangeRequestDTONew = new AccountAsyncChangeExtDTO();
                        accountAsyncChangeRequestDTO.setAmount(biz.getCapital());
                        BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChangeRequestDTONew);
                        List<SaveBillDetailRequest> saveBillDetailRequestList = new ArrayList<>();
                        SaveBillDetailRequest detailRequest = new SaveBillDetailRequest();
                        detailRequest.setAmount(biz.getCapital());
                        if (biz.getBizType().equals(BusinessTypeEnum.COMPENSATORY.getValue())) {
                            detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_CORPUS_GUARANTEE_COMPANY);
                            detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_CORPUS);
                        } else if (biz.getBizType().equals(BusinessTypeEnum.REPAYMENT.getValue())){
                            detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_CORPUS_BORROW);
                            detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_CORPUS);
                        }else {
                            detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PRINCIPAL);
                        }

                        detailRequest.setCurrentPeriod(currentPeriod);
                        detailRequest.setRelationUserId(borrowerUserId);
                        detailRequest.setRelationAccountId(biz.getSourceAccountId());
                        saveBillDetailRequestList.add(detailRequest);

                        accountAsyncChangeRequestDTONew.setSecondSortCode(detailRequest.getBillSecondSubjectEnum().getCode());
                        accountAsyncChangeRequestDTONew.setSaveBillDetailRequestList(saveBillDetailRequestList);
                        dtoList.add(accountAsyncChangeRequestDTONew);
                    }
                    //罚息
                    //借款罚息
                    if (biz.getPenaltyFee().compareTo(BigDecimal.ZERO) > 0) {
                        log.info("biz.getPenaltyFee()={}", biz.getPenaltyFee());
                        //投资收益
                        MoneyTotalDTO incomeFromInvestment = new MoneyTotalDTO();
                        incomeFromInvestment.setAccountId(biz.getTargetAccountId());
                        incomeFromInvestment.setAmount(biz.getPenaltyFee());
                        incomeFromInvestment.setAmountType(AccountAmountTypeEnum.INVEST_INCOME);
                        moneyTotalDTOList.add(incomeFromInvestment);

                        MoneyTotalDTO penaltyFee = new MoneyTotalDTO();
                        penaltyFee.setAccountId(biz.getSourceAccountId());
                        penaltyFee.setAmount(biz.getPenaltyFee());
                        penaltyFee.setAmountType(AccountAmountTypeEnum.BORROW_PENALTY_FEE);
                        moneyTotalDTOList.add(penaltyFee);

                        AccountAsyncChangeExtDTO accountAsyncChangeRequestDTONew = new AccountAsyncChangeExtDTO();
                        accountAsyncChangeRequestDTO.setAmount(biz.getPenaltyFee());
                        BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChangeRequestDTONew);
                        List<SaveBillDetailRequest> saveBillDetailRequestList = new ArrayList<>();
                        SaveBillDetailRequest detailRequest = new SaveBillDetailRequest();
                        detailRequest.setAmount(biz.getPenaltyFee());
                        if (biz.getBizType().equals(BusinessTypeEnum.COMPENSATORY.getValue())) {
                            detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_PENALTY_GUARANTEE_COMPANY);
                            detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_PENALTY);
                        } else if (biz.getBizType().equals(BusinessTypeEnum.REPAYMENT.getValue())){
                            detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_OVERDUE_FEE_BORROW);
                            detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_PENALTY);
                        }else {
                            detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PENALTY);
                        }

                        detailRequest.setCurrentPeriod(currentPeriod);
                        detailRequest.setRelationUserId(borrowerUserId);
                        detailRequest.setRelationAccountId(biz.getSourceAccountId());
                        saveBillDetailRequestList.add(detailRequest);

                        accountAsyncChangeRequestDTONew.setSecondSortCode(detailRequest.getBillSecondSubjectEnum().getCode());
                        accountAsyncChangeRequestDTONew.setSaveBillDetailRequestList(saveBillDetailRequestList);
                        dtoList.add(accountAsyncChangeRequestDTONew);
                    }
                    //借款担保费
                    if (biz.getGuaranteeFee().compareTo(BigDecimal.ZERO) > 0) {
                        log.info("biz.getGuaranteeFee()={}", biz.getGuaranteeFee());
                        MoneyTotalDTO guaranteeFee = new MoneyTotalDTO();
                        guaranteeFee.setAccountId(biz.getSourceAccountId());
                        guaranteeFee.setAmount(biz.getGuaranteeFee());
                        guaranteeFee.setAmountType(AccountAmountTypeEnum.BORROW_GUARANTEE_SERVICE_FEE);
                        moneyTotalDTOList.add(guaranteeFee);


                        AccountAsyncChangeExtDTO accountAsyncChangeRequestDTONew = new AccountAsyncChangeExtDTO();
                        accountAsyncChangeRequestDTO.setAmount(biz.getGuaranteeFee());
                        BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChangeRequestDTONew);
                        List<SaveBillDetailRequest> saveBillDetailRequestList = new ArrayList<>();
                        SaveBillDetailRequest detailRequest = new SaveBillDetailRequest();
                        detailRequest.setAmount(biz.getGuaranteeFee());
                        detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_IN_REPAYMENT);
                        detailRequest.setCurrentPeriod(currentPeriod);
                        detailRequest.setRelationUserId(borrowerUserId);
                        detailRequest.setRelationAccountId(biz.getSourceAccountId());
                        saveBillDetailRequestList.add(detailRequest);

                        accountAsyncChangeRequestDTONew.setSecondSortCode(detailRequest.getBillSecondSubjectEnum().getCode());
                        accountAsyncChangeRequestDTONew.setSaveBillDetailRequestList(saveBillDetailRequestList);
                        dtoList.add(accountAsyncChangeRequestDTONew);
                    }

                    //计算累计还款金额
                    MoneyTotalDTO refundAmount = new MoneyTotalDTO();
                    refundAmount.setAccountId(biz.getSourceAccountId());
                    refundAmount.setAmount(biz.getAmount());
                    refundAmount.setAmountType(AccountAmountTypeEnum.REPAYMENT_TOTAL);
                    moneyTotalDTOList.add(refundAmount);

                    AccountAsyncChange accountAsyncChange = new AccountAsyncChange();
                    BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChange);
                    accountAsyncChange.setCreateTime(new Date());
                    accountAsyncChangeMapper.insertSelective(accountAsyncChange);

                }
                //BatchTransOrder batchTransOrder = batchTransOrderMapperExt.selectOrderByBatchRequestNo(batchTransOrderDetail.getBatchRequestNo());
                try {
                    if (TransactionTypeEnum.COMPENSATORY.getValue().equals(batchTransOrder.getTradeType())) {
                        billFacade.successBillByOrderId(lanMaoProperties.getNiiWooAccount().getGuaranteeUserId(), proTransactionOrders.getId().toString(), OrderTypeEnum.GUARANTEE);
                    } else {
                        billFacade.successBillByOrderId(batchTransOrder.getBorrowerUserId(), proTransactionOrders.getId().toString(), OrderTypeEnum.REPAYMENT);
                    }
                } catch (Exception e) {
                    log.error("niiwooBillFacade successBillByOrderId failed--", e);
                    throw e;
                }
                if (proTransactionOrders != null && !TransactionTypeEnum.COMPENSATORY.getValue().equals(batchTransOrder.getTradeType())) {
                    JSONObject obj = new JSONObject();
                    obj.put("accountId", proTransactionOrders.getAccountId());
                    obj.put("borrowerUserId", borrowerUserId);
                    obj.put("amount", proTransactionOrders.getAmount().negate());
                    refundFreezeMap.put(proTransactionOrders.getBatchRequestNo(), obj);
                    //借款利息
                    MoneyTotalDTO interestAmount = new MoneyTotalDTO();
                    interestAmount.setAccountId(proTransactionOrders.getAccountId());
                    interestAmount.setUserId(borrowerUserId);
                    interestAmount.setAmount(interestTotal);
                    interestAmount.setAmountType(AccountAmountTypeEnum.BORROW_INTEREST);
                    moneyTotalDTOList.add(interestAmount);
                }
            }
        }
        log.info("refundFreezeMap={}", JSON.toJSONString(refundFreezeMap));
        refundFreezeMap.forEach((k, v) -> {
            Long accountId = v.getLong("accountId");
            String borrowerUserId = v.getString("borrowerUserId");
            BigDecimal amount = v.getBigDecimal("amount");
            //还款冻结-
            MoneyTotalDTO refundFreeze = new MoneyTotalDTO();
            refundFreeze.setAccountId(accountId);
            refundFreeze.setUserId(borrowerUserId);
            refundFreeze.setAmount(amount);
            refundFreeze.setAmountType(AccountAmountTypeEnum.REPAYMENT_FREEZE);
            moneyTotalDTOList.add(refundFreeze);
        });

        accountBalanceLocalAsyncService.accountAsyncChangeLocal(dtoList);

        return moneyTotalDTOList;
    }



    @Autowired
    private AccountBalanceLocalService accountBalanceLocalService;

    /**
     * 用于补单 用后屏蔽
     */
    @Transactional
    @Deprecated
    public void completJobForBill() {

        /**
         *
         * select t1.* from t_ac_batch_trans_order_detail_biz t1
         inner join t_ac_batch_trans_order_detail t2 on t2.id = t1.trans_detail_order_id
         where t2.`status` = 2
         and not exists (select 1 from t_ac_account_bill_base t3 where t3.request_no = t1.detail_request_no);
         */
//        log.info("用于补单,账单被单start");
//        List<AccountAsyncChangeExtDTO> dtoList = new ArrayList<>();
//        List<BatchTransOrderDetailBiz> list = batchTransOrderDetailBizMapperExt.queryDetailRequestBizsForBill();
//        if (list!=null){
//            log.info("查询结果待被单数据 list={}",list.size());
//        }else {
//            log.info("list=null----------------");
//        }
//        for (BatchTransOrderDetailBiz biz : list) {
//            log.info("updateAllAccountAmount.dto--{}", JSON.toJSONString(biz));
//            BatchTransOrder batchTransOrder = batchTransOrderMapperExt.selectOrderByBatchRequestNo(biz.getBatchRequestNo());
//            String borrowerUserId = batchTransOrder.getBorrowerUserId();
//            // for (BatchTransOrderDetailBiz biz : bizList) {
//            log.info("DetailRequestNo={},amount={}", biz.getDetailRequestNo(), biz.getAmount());
//            AccountAsyncChangeExtDTO accountAsyncChangeRequestDTO = new AccountAsyncChangeExtDTO();
//            if (biz.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
//                continue;
//            }
//            accountAsyncChangeRequestDTO.setId(snowflakeIdWorker.nextId());
//            accountAsyncChangeRequestDTO.setStatus((byte) 1);//初始状态
//            accountAsyncChangeRequestDTO.setAccountId(biz.getTargetAccountId());
//            //accountAsyncChangeRequestDTO.setAmount(biz.getAmount());
//            accountAsyncChangeRequestDTO.setProjectId(batchTransOrder.getProjectId());
//            accountAsyncChangeRequestDTO.setRequestNo(biz.getDetailRequestNo());
//            accountAsyncChangeRequestDTO.setRelationUserId(borrowerUserId);
//            accountAsyncChangeRequestDTO.setOrderId(biz.getTransDetailOrderId());
//            accountAsyncChangeRequestDTO.setSecondSortCode("0");//默认值，无费用科目时,理论上不存在此场景
//            accountAsyncChangeRequestDTO.setInvestOrderId(biz.getInvestOrderId());
//
//            //如果有利息,计算投资收益和待收利息
//            if (biz.getInterest().compareTo(BigDecimal.ZERO) > 0) {
//                AccountAsyncChangeExtDTO accountAsyncChangeRequestDTONew = new AccountAsyncChangeExtDTO();
//                accountAsyncChangeRequestDTO.setAmount(biz.getInterest());
//                BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChangeRequestDTONew);
//                List<SaveBillDetailRequest> saveBillDetailRequestList = new ArrayList<>();
//                SaveBillDetailRequest detailRequest = new SaveBillDetailRequest();
//                detailRequest.setBackTime(null);
//                detailRequest.setAmount(biz.getInterest());
//                if (biz.getBizType().equals(BusinessTypeEnum.COMPENSATORY.getValue())) {
//                    //担保公司--》投资人
//                    detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_INTEREST_GUARANTEE_COMPANY);
//                    detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_INTEREST);
//
//                } else if (biz.getBizType().equals(BusinessTypeEnum.REPAYMENT.getValue())) {
//                    //借款人-》投资人
//                    detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_INTEREST_BORROW);
//                    detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_INTEREST);
//
//                } else {
//                    //借款人-》担保公司
//                    detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_INTEREST);
//                }
//
//                detailRequest.setCurrentPeriod(batchTransOrder.getCurrentPeriod());
//                detailRequest.setRelationUserId(borrowerUserId);
//                detailRequest.setRelationAccountId(biz.getSourceAccountId());
//                saveBillDetailRequestList.add(detailRequest);
//
//                accountAsyncChangeRequestDTONew.setSecondSortCode(detailRequest.getBillSecondSubjectEnum().getCode());
//                accountAsyncChangeRequestDTONew.setSaveBillDetailRequestList(saveBillDetailRequestList);
//                dtoList.add(accountAsyncChangeRequestDTONew);
//            }
//            //如果有平台管理费,计算借款费用
//            if (biz.getManageFee().compareTo(BigDecimal.ZERO) > 0) {
//                log.info("biz.getManageFee()={}", biz.getManageFee());
//                AccountAsyncChangeExtDTO accountAsyncChangeRequestDTONew = new AccountAsyncChangeExtDTO();
//                accountAsyncChangeRequestDTO.setAmount(biz.getManageFee());
//                BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChangeRequestDTONew);
//                List<SaveBillDetailRequest> saveBillDetailRequestList = new ArrayList<>();
//                SaveBillDetailRequest detailRequest = new SaveBillDetailRequest();
//                detailRequest.setAmount(biz.getManageFee());
//                detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.PLATFORM_SERVICE_FEE_IN_MANAGE_SPEED_BORROWING);
//                detailRequest.setCurrentPeriod(batchTransOrder.getCurrentPeriod());
//                detailRequest.setRelationUserId(borrowerUserId);
//                detailRequest.setRelationAccountId(biz.getSourceAccountId());
//                saveBillDetailRequestList.add(detailRequest);
//
//                accountAsyncChangeRequestDTONew.setSecondSortCode(detailRequest.getBillSecondSubjectEnum().getCode());
//                accountAsyncChangeRequestDTONew.setSaveBillDetailRequestList(saveBillDetailRequestList);
//                dtoList.add(accountAsyncChangeRequestDTONew);
//            }
//
//            //如果有本金,计算待收本金
//            if (biz.getCapital().compareTo(BigDecimal.ZERO) > 0) {
//                log.info("biz.getCapital()={}", biz.getCapital());
//
//                AccountAsyncChangeExtDTO accountAsyncChangeRequestDTONew = new AccountAsyncChangeExtDTO();
//                accountAsyncChangeRequestDTO.setAmount(biz.getCapital());
//                BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChangeRequestDTONew);
//                List<SaveBillDetailRequest> saveBillDetailRequestList = new ArrayList<>();
//                SaveBillDetailRequest detailRequest = new SaveBillDetailRequest();
//                detailRequest.setAmount(biz.getCapital());
//                if (biz.getBizType().equals(BusinessTypeEnum.COMPENSATORY.getValue())) {
//                    detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_CORPUS_GUARANTEE_COMPANY);
//                    detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_CORPUS);
//                } else if (biz.getBizType().equals(BusinessTypeEnum.REPAYMENT.getValue())) {
//                    detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_CORPUS_BORROW);
//                    detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_CORPUS);
//                } else {
//                    detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PRINCIPAL);
//                }
//
//                detailRequest.setCurrentPeriod(batchTransOrder.getCurrentPeriod());
//                detailRequest.setRelationUserId(borrowerUserId);
//                detailRequest.setRelationAccountId(biz.getSourceAccountId());
//                saveBillDetailRequestList.add(detailRequest);
//
//                accountAsyncChangeRequestDTONew.setSecondSortCode(detailRequest.getBillSecondSubjectEnum().getCode());
//                accountAsyncChangeRequestDTONew.setSaveBillDetailRequestList(saveBillDetailRequestList);
//                dtoList.add(accountAsyncChangeRequestDTONew);
//            }
//            //罚息
//            //借款罚息
//            if (biz.getPenaltyFee().compareTo(BigDecimal.ZERO) > 0) {
//                log.info("biz.getPenaltyFee()={}", biz.getPenaltyFee());
//                //投资收益
//                AccountAsyncChangeExtDTO accountAsyncChangeRequestDTONew = new AccountAsyncChangeExtDTO();
//                accountAsyncChangeRequestDTO.setAmount(biz.getPenaltyFee());
//                BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChangeRequestDTONew);
//                List<SaveBillDetailRequest> saveBillDetailRequestList = new ArrayList<>();
//                SaveBillDetailRequest detailRequest = new SaveBillDetailRequest();
//                detailRequest.setAmount(biz.getPenaltyFee());
//                if (biz.getBizType().equals(BusinessTypeEnum.COMPENSATORY.getValue())) {
//                    detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_PENALTY_GUARANTEE_COMPANY);
//                    detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_PENALTY);
//                } else if (biz.getBizType().equals(BusinessTypeEnum.REPAYMENT.getValue())) {
//                    detailRequest.setBillRemark3Enum(BillRemark3Enum.INVESTMENT_PAYBACK_OVERDUE_FEE_BORROW);
//                    detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_INVEST_REPAYMENT_PENALTY);
//                } else {
//                    detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_IN_REPAYMENT_PENALTY);
//                }
//
//                detailRequest.setCurrentPeriod(batchTransOrder.getCurrentPeriod());
//                detailRequest.setRelationUserId(borrowerUserId);
//                detailRequest.setRelationAccountId(biz.getSourceAccountId());
//                saveBillDetailRequestList.add(detailRequest);
//
//                accountAsyncChangeRequestDTONew.setSecondSortCode(detailRequest.getBillSecondSubjectEnum().getCode());
//                accountAsyncChangeRequestDTONew.setSaveBillDetailRequestList(saveBillDetailRequestList);
//                dtoList.add(accountAsyncChangeRequestDTONew);
//            }
//            //借款担保费
//            if (biz.getGuaranteeFee().compareTo(BigDecimal.ZERO) > 0) {
//                log.info("biz.getGuaranteeFee()={}", biz.getGuaranteeFee());
//                AccountAsyncChangeExtDTO accountAsyncChangeRequestDTONew = new AccountAsyncChangeExtDTO();
//                accountAsyncChangeRequestDTO.setAmount(biz.getGuaranteeFee());
//                BeanUtils.copyProperties(accountAsyncChangeRequestDTO, accountAsyncChangeRequestDTONew);
//                List<SaveBillDetailRequest> saveBillDetailRequestList = new ArrayList<>();
//                SaveBillDetailRequest detailRequest = new SaveBillDetailRequest();
//                detailRequest.setAmount(biz.getGuaranteeFee());
//                detailRequest.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_IN_REPAYMENT);
//                detailRequest.setCurrentPeriod(batchTransOrder.getCurrentPeriod());
//                detailRequest.setRelationUserId(borrowerUserId);
//                detailRequest.setRelationAccountId(biz.getSourceAccountId());
//                saveBillDetailRequestList.add(detailRequest);
//                accountAsyncChangeRequestDTONew.setSecondSortCode(detailRequest.getBillSecondSubjectEnum().getCode());
//                accountAsyncChangeRequestDTONew.setSaveBillDetailRequestList(saveBillDetailRequestList);
//                dtoList.add(accountAsyncChangeRequestDTONew);
//            }
//
//        }
//
//        for (AccountAsyncChangeExtDTO extDto : dtoList) {
//            accountBalanceLocalService.accountAsyncChangeCompleteJob(extDto);
//        }
    }
}
